package cn.jbolt.util;

import org.springframework.stereotype.Component;

import java.util.concurrent.*;
import java.util.Map;

@Component
public class CacheUtil<K, V> {
    //key
    public static final String KEY_QINIU_TOKEN = "qiniuToken";
    public static final String KEY_APP_CONFIG = "appConfig";
    public static final String KEY_APP_SESSION = "appSession";
    public static final String KEY_APP = "app";

    // 静态缓存实例
    private static final Map<String, CacheEntry<String>> stringCache = new ConcurrentHashMap<>();
    private static final Map<String, CacheEntry<?>> objectCache = new ConcurrentHashMap<>();
    private static final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);

    // 私有构造函数防止实例化
    private CacheUtil() {
    }

    /**
     * 将一个字符串放入缓存中
     *
     * @param key      缓存键
     * @param value    缓存值（字符串）
     * @param duration 过期时间（-1表示永不过期）
     * @param unit     时间单位
     */
    public static void putString(String key, String value, long duration, TimeUnit unit) {
        if (duration == -1) {
            // 如果duration为-1，则不安排过期任务
            stringCache.put(key, new CacheEntry<>(value, System.nanoTime(), Long.MAX_VALUE));
        } else {
            CacheEntry<String> entry = new CacheEntry<>(value, System.nanoTime(), unit.toNanos(duration));
            stringCache.put(key, entry);

            // 安排一个任务在指定时间后移除该条目
            scheduler.schedule(() -> stringCache.remove(key), duration, unit);
        }
    }

    /**
     * 从缓存中获取一个字符串
     *
     * @param key 缓存键
     * @return 缓存值或null（如果不存在或已过期）
     */
    public static String getString(String key) {
        CacheEntry<String> entry = stringCache.get(key);
        if (entry == null) return null;

        // 检查是否已经过期
        if (isExpired(entry)) {
            stringCache.remove(key);
            return null;
        }
        return entry.getValue();
    }

    /**
     * 将一个对象放入缓存中
     *
     * @param <T>      缓存值的类型
     * @param key      缓存键
     * @param value    缓存值（任意对象）
     * @param duration 过期时间（-1表示永不过期）
     * @param unit     时间单位
     */
    @SuppressWarnings("unchecked")
    public static <T> void putObject(String key, T value, long duration, TimeUnit unit) {
        if (duration == -1) {
            // 如果duration为-1，则不安排过期任务
            objectCache.put(key, new CacheEntry<>(value, System.nanoTime(), Long.MAX_VALUE));
        } else {
            CacheEntry<T> entry = new CacheEntry<>(value, System.nanoTime(), unit.toNanos(duration));
            objectCache.put(key, entry);

            // 安排一个任务在指定时间后移除该条目
            scheduler.schedule(() -> objectCache.remove(key), duration, unit);
        }
    }

    /**
     * 从缓存中获取一个对象
     *
     * @param <T> 缓存值的类型
     * @param key 缓存键
     * @return 缓存值或null（如果不存在或已过期）
     */
    @SuppressWarnings("unchecked")
    public static <T> T getObject(String key) {
        CacheEntry<?> entry = objectCache.get(key);
        if (entry == null) return null;

        // 检查是否已经过期
        if (isExpired(entry)) {
            objectCache.remove(key);
            return null;
        }
        return (T) entry.getValue();
    }

    /**
     * 从缓存中移除一个字符串
     *
     * @param key 缓存键
     */
    public static void removeString(String key) {
        stringCache.remove(key);
    }

    /**
     * 从缓存中移除一个对象
     *
     * @param key 缓存键
     */
    public static void removeObject(String key) {
        objectCache.remove(key);
    }

    private static boolean isExpired(CacheEntry<?> entry) {
        return (System.nanoTime() - entry.getTimestamp()) > entry.getDuration();
    }

    // 清理资源
    public static void shutdown() {
        scheduler.shutdown();
    }

    // 内部类：用于存储缓存条目的信息（值、时间戳和持续时间）
    private static class CacheEntry<V> {
        private final V value;
        private final long timestamp;
        private final long duration;

        public CacheEntry(V value, long timestamp, long duration) {
            this.value = value;
            this.timestamp = timestamp;
            this.duration = duration;
        }

        public V getValue() {
            return value;
        }

        public long getTimestamp() {
            return timestamp;
        }

        public long getDuration() {
            return duration;
        }
    }
    // 测试代码
//    public static void main(String[] args) throws InterruptedException {
//        // 将七牛云Token放入缓存，设置过期时间为5秒
//        CacheUtil.put(KEY_QINIU_TOKEN, "your-qiniu-token", 5, TimeUnit.SECONDS);
//
//        // 立即获取Token
//        System.out.println("Immediately: " + CacheUtil.get(KEY_QINIU_TOKEN));
//
//        // 等待6秒后再尝试获取Token
//        Thread.sleep(6000);
//        System.out.println("After 6 seconds: " + CacheUtil.get(KEY_QINIU_TOKEN));
//
//        // 关闭调度器
//        CacheUtil.shutdown();
//    }
}
